home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus Leser 15
/
Amiga Plus Leser CD 15.iso
/
Tools
/
Development
/
mmu
/
MuManual
/
C_Sources
/
MMUCacheTest.c
< prev
next >
Wrap
C/C++ Source or Header
|
2002-03-12
|
13KB
|
365 lines
/*********************************************************
** MMUCacheTest **
** test whether the pre/postDMA functions work **
** correctly **
** Version 0.25 14th Mar 1998 **
** THOR-Software, Thomas Richter **
*********************************************************/
/// Includes
#include <exec/types.h>
#include <exec/ports.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <exec/execbase.h>
#include <mmu/mmubase.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/filehandler.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/mmu.h>
#include <string.h>
#include <stdio.h>
///
/// Defines
#define REVISION 10
#define STRINGVERSION "0.25"
#define STRINGDATE "14.3.99"
#define NUMARGS 1L
#define BUFSIZE (128L*1024L)
#define MAJIK1 ('Test')
#define MAJIK2 (0xaa55ff00)
#define MAJIK3 (0x11223344)
#define MAJIK4 ('THOR')
#define RETRIES 64
///
/// Statics
struct MMUBase *MMUBase;
extern struct DosLibrary *DOSBase;
extern struct ExecBase *SysBase;
struct MsgPort *ioport;
struct IOStdReq *io;
///
/// Prototypes
void FlushLibs(void);
int RunTests(char *devicename);
int main(int argc,char **argv);
int AccessDevice(void);
ULONG CheckSum(ULONG *buf,ULONG size);
///
char version[]="$VER: MMUCacheTest " STRINGVERSION " (" STRINGDATE ") © THOR";
/// main
int main(int argc,char **argv)
{
char *devicename;
int len;
int rc=0;
FlushLibs();
printf( "MMUCacheTest " STRINGVERSION " (" STRINGDATE ") © THOR.\n"
"Internal use only, no commercial use.\n");
if ((argc<2) || (argc>3) || (!strcmp(argv[1],"?"))) {
printf("\nThis program reads from your HD to check whether the\n"
"cache control functions of the mmu.library work\n"
"correctly. It does not write to the HD at all and won't\n"
"harm your data.\n\n"
"Usage: %s device_name: [nommu]\n\n",argv[0]);
} else {
if (argc==2) {
MMUBase=(struct MMUBase *)OpenLibrary(MMU_NAME,0);
} else MMUBase=0;
devicename=argv[1];
len=strlen(devicename);
if (devicename[len-1]!=':') {
printf("The device name must be given with a colon at the\n"
"end, e.g. DH0:\n\n");
rc=5;
} else {
devicename[len-1]=0;
rc=RunTests(devicename);
}
if (MMUBase) CloseLibrary((struct Library *)MMUBase);
}
return rc;
}
///
/// RunTests
int RunTests(char *devicename)
{
struct DosList *dl;
struct DosEnvec *env;
struct FileSysStartupMsg *fstart;
char *devname;
int len;
ULONG unit,flags;
char device[256];
BOOL locked=TRUE;
int rc=10;
if (dl=LockDosList(LDF_DEVICES|LDF_READ)) {
if (dl=FindDosEntry(dl,devicename,LDF_DEVICES|LDF_READ)) {
fstart=BADDR(dl->dol_misc.dol_handler.dol_Startup);
if (TypeOfMem(fstart)) {
if (fstart->fssm_Unit<0x400) {
env=BADDR(fstart->fssm_Environ);
if (TypeOfMem(env)) {
unit=fstart->fssm_Unit;
flags=fstart->fssm_Flags;
devname=BADDR(fstart->fssm_Device);
if (TypeOfMem(devname)) {
len=devname[0];
memcpy(device,devname+1,len);
device[len]=0;
UnLockDosList(LDF_DEVICES|LDF_READ);
locked=FALSE;
if (ioport=CreateMsgPort()) {
if (io=(struct IOStdReq *)CreateIORequest(ioport,sizeof(struct IOStdReq))) {
if (!OpenDevice(device,unit,(struct IORequest *)io,flags)) {
rc=AccessDevice();
CloseDevice((struct IORequest *)io);
} else printf("Failed to open the %s.\n",device);
DeleteIORequest((struct IORequest *)io);
} else printf("Failed to allocate the IORequest.\n");
DeleteMsgPort(ioport);
} else printf("Failed to create the IO message port.\n");
} else rc=5;
} else rc=5;
} else rc=5;
} else rc=5;
if (rc==5) {
printf("The selected device is not a direct block I/O device.\n"
"Please specify a FAST DMA device for testiing.\n");
}
} else printf("Sorry, %s: is either not mounted or not a device.\n"
"Please DO NOT specify volumes or assigns.\n",devicename);
if (locked)
UnLockDosList(LDF_DEVICES|LDF_READ);
}
return rc;
}
///
/// AccessDevice
int AccessDevice(void)
{
ULONG *buffer;
UBYTE *mem;
int i;
int error;
ULONG sum;
ULONG discount;
ULONG accesscount;
volatile ULONG check,*ptr,*ptr2; /* make sure these are really read */
long pri;
ULONG mask;
/* Allocate memory aligned to cache line boundaries */
mem=AllocMem(BUFSIZE+16*3,MEMF_PUBLIC);
if (!mem) {
printf("Out of memory, sorry!\n");
return 20;
}
buffer=(ULONG *)(((ULONG)(mem+15)) & 0xfffffff0);
if (MMUBase) {
printf("mmu.library loaded.\n");
} else printf("mmu.library not utilized.\n");
/* Fill in some magic stuff */
ptr=buffer;
ptr2=buffer+8+BUFSIZE; /* to the end of the buffer */
buffer[0]=MAJIK1;
buffer[1]=MAJIK2;
buffer[2]=MAJIK3;
buffer[3]=MAJIK4;
CacheClearU();
/* Make sure the stuff is really in memory */
printf("Initial read, calculate checksum.\n");
io->io_Command=CMD_READ;
io->io_Length=BUFSIZE;
io->io_Offset=0; /* well, whereever... this doesn't really matter... */
io->io_Data=buffer;
error=DoIO((struct IORequest *)io);
if (error) {
printf("Can't read from the device, failure code %ld.\n",error);
goto error; /* bah! */
}
sum=CheckSum(buffer,BUFSIZE>>2);
printf("\nRunning the initial device test.\n"
"This test checks whether the connected device works reliable.\n"
"It does NOT check the MMU code which is not needed for this\n"
"initial run.\n"
"This test SHOULD NOT fail. In case it does, your device or\n"
"host adapter is broken, but not the MMU logic.\n\n"
"In case you're running any disk cache program, e.g. DynamiCache,\n"
"you should disable it for this test. The test won't test anything\n"
"if any kind of disk cache is active!\n\n");
for(i=0;i<RETRIES;i++) {
/* For general entertainment, read data from somewhere else.
This should hopefully disable caching of the device. */
io->io_Command=CMD_READ;
io->io_Length=BUFSIZE;
io->io_Offset=800L*1024L; /* well, whereever... this doesn't really matter... */
io->io_Data=buffer;
error=DoIO((struct IORequest *)io);
if (error) {
printf("Can't read from the device, failure code %ld.\n",error);
goto error; /* bah! */
}
buffer[0]=MAJIK1;
buffer[1]=MAJIK2;
buffer[2]=MAJIK3;
buffer[3]=MAJIK4;
CacheClearU();
/* Make sure the stuff is really in memory */
io->io_Command=CMD_READ;
io->io_Length=BUFSIZE;
io->io_Offset=0;
io->io_Data=buffer;
error=DoIO((struct IORequest *)io);
if (error) {
printf("Can't read from the device, failure code %ld.\n",error);
goto error; /* bah! */
}
if (sum!=CheckSum(buffer,BUFSIZE>>2)) {
printf("FATAL ERROR: Device read does not work reliable!\n"
"Test failed. Looks like your hardware is broken, sorry.\n");
goto error;
}
}
printf("The initial test passed.\n");
accesscount=0;
discount=0;
printf("\nRunning the real test. If this test fails, something is wrong\n"
"with the CachePreDMA/CachePostDMA logic. In this case, please\n"
"sent me an EMail so I can fix it.\n");
for(i=0;i<RETRIES;i++) {
/* For general entertainment, read data from somewhere else.
This should hopefully disable caching of the device. */
io->io_Command=CMD_READ;
io->io_Length=BUFSIZE;
io->io_Offset=800L*1024L; /* well, whereever... this doesn't really matter... */
io->io_Data=buffer;
error=DoIO((struct IORequest *)io);
if (error) {
printf("Can't read from the device, failure code %ld.\n",error);
goto error; /* bah! */
}
/* start at a non-aligned address */
io->io_Command=CMD_READ;
io->io_Length=BUFSIZE;
io->io_Offset=0;
io->io_Data=buffer+8;
mask=(1<<i)-1;
pri=SetTaskPri(FindTask(NULL),1);
CacheClearU();
/* Push some stuff into the cache */
buffer[0]=MAJIK1;
buffer[1]=MAJIK2;
buffer[2]=MAJIK3;
buffer[3]=MAJIK4;
/* Now start the IO, asynchronously */
SendIO((struct IORequest *)io);
while (((UBYTE)(SysBase->IDNestCnt))!=0xff || ((UBYTE)(SysBase->TDNestCnt))!=0xff) {
Delay(2L);
discount++;
}
/* access the memory while the IO is active */
while(!CheckIO((struct IORequest *)io)) {
check=*ptr;
check=*ptr2;
accesscount++;
if ((accesscount & mask)==0) {
(*ptr)++;
(*ptr2)++;
}
}
SetTaskPri(FindTask(NULL),pri);
error=WaitIO((struct IORequest *)io);
if (error) {
printf("Can't read from the device, failure code %ld.\n",error);
goto error; /* bah! */
}
if (sum!=CheckSum(buffer+8,BUFSIZE>>2)) {
printf("The MMU cache test failed. There seems to be a bug in\n"
"the CachePre/PostDMA functions. Please let me know!\n\n");
goto error;
}
}
printf("The MMU cache test passed.\n"
"Task switching was disabled %ld times, run %lu RAM accesses.\n",discount,accesscount);
Delay(100L);
FreeMem(mem,BUFSIZE+16*3);
return 0;
error:
FreeMem(mem,BUFSIZE+16*3);
return 10;
}
///
/// CheckSum
/* Calculate a hopefully somewhat useable checksum for the buffer. Size
is in long words */
ULONG CheckSum(ULONG *buf,ULONG size)
{
ULONG sum=0;
while(size) {
sum += *buf;
sum ^= size;
if (sum & 0x01) {
sum >>= 1;
sum |= 0x80000000;
} else sum >>= 1;
buf++;
size--;
}
return sum;
}
///
/// FlushLibs
void FlushLibs(void)
{
void *mem;
if (mem=AllocMem(0x7ffffff0,MEMF_PUBLIC))
FreeMem(mem,0x7ffffff0);
}
///